package com.biodiv.community.manager.mq;

import com.alibaba.fastjson2.JSONObject;
import com.biodiv.community.enums.TopicEnum;
import com.biodiv.community.event.BaseEvent;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import com.biodiv.community.utils.SpringUtils;

import java.lang.reflect.ParameterizedType;

import static com.biodiv.community.constant.CommonConstant.TRACE_ID;

/**
 * @author tianquan
 */
@Slf4j
public abstract class RedisListener<T extends BaseEvent> implements MessageListener {

    protected ApplicationEventPublisher eventPublisher;

    protected Class<T> eventClass;

    protected abstract void handleMessage(T event);

    @Override
    public void onMessage(@NotNull Message message, byte[] pattern) {
        if (eventPublisher == null) {
            eventPublisher = SpringUtils.getApplicationContext();
        }
        // 解析消息
        T event = JSONObject.parseObject(new String(message.getBody()), getEventClass());
        // 消息去重
        if (!checkMessage(event.getMessageId())) {
            log.info("Duplicate message: {} traceId: {}", event.getMessageId(), event.getTraceId());
            return;
        }
        // 设置traceId
        MDC.put(TRACE_ID, event.getTraceId());
        // 发送事件
        eventPublisher.publishEvent(event);
    }

    public Class<T> getEventClass() {
        if (eventClass == null) {
            eventClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return eventClass;
    }

    public abstract TopicEnum getTopic();

    protected boolean checkMessage(String messageId) {
        // todo 检测消息是否重复
        return true;
    }

}